package pl.edu.mimuw.irs.core.util;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import pl.edu.mimuw.irs.core.model.design.exception.InternalDesignException;
import pl.edu.mimuw.irs.core.model.design.exception.InternalDesignException.DesignCause;
import pl.edu.mimuw.irs.core.model.design.net.IRSActivity;
import pl.edu.mimuw.irs.core.model.design.net.IRSArc;
import pl.edu.mimuw.irs.core.model.design.net.IRSNode;
import pl.edu.mimuw.irs.core.model.design.net.IRSPlace;
import pl.edu.mimuw.irs.core.model.design.net.IRSRequirement;
import pl.edu.mimuw.irs.core.model.design.net.IRSTransition;
import pl.edu.mimuw.irs.core.model.design.net.IRSWorkflow;
import pl.edu.mimuw.irs.core.model.petrinet.Arc;
import pl.edu.mimuw.irs.core.model.petrinet.INode;
import pl.edu.mimuw.irs.core.model.petrinet.Net;
import pl.edu.mimuw.irs.core.model.petrinet.Place;
import pl.edu.mimuw.irs.core.model.petrinet.Transition;

/**
 * @author Jakub Rauch
 * Created on: 2009-05-24
 */
public class Converter {

	// *** Static methods
	
	public static IRSArc asIRSArc(Arc arc) {
		if (!(arc instanceof IRSArc)) 
			throw new InternalDesignException(DesignCause.NOT_IRS_ARC, arc.toString());
		return (IRSArc)arc;
	}

	public static IRSNode asIRSNode(INode node) {
		if (!(node instanceof IRSNode)) 
			throw new InternalDesignException(DesignCause.NOT_IRS_NODE, node.toString());
		return (IRSNode)node;
	}
	
	public static IRSPlace asIRSPlace(Place place) {
		if (!(place instanceof IRSPlace)) 
			throw new InternalDesignException(DesignCause.NOT_IRS_PLACE, place.toString());
		return (IRSPlace)place;
	}

	public static IRSRequirement asIRSRequirement(INode node) {
		if (!(node instanceof IRSRequirement)) 
			throw new InternalDesignException(DesignCause.NOT_IRS_REQUIREMENT, node.toString());
		return (IRSRequirement)node;
	}

	public static IRSActivity asIRSActivity(IRSNode node) {
		if (!(node instanceof IRSActivity)) 
			throw new InternalDesignException(DesignCause.NOT_IRS_ACTIVITY, node.toString());
		return (IRSActivity)node;
	}

	public static IRSPlace asIRSPlace(IRSNode place) {
		if (!(place instanceof IRSPlace)) 
			throw new InternalDesignException(DesignCause.NOT_IRS_PLACE, place.toString());
		return (IRSPlace)place;
	}
	
	public static IRSTransition asIRSTransition(Transition transition) {
		if (!(transition instanceof IRSTransition)) 
			throw new InternalDesignException(DesignCause.NOT_IRS_TRANSITION, transition.toString());
		return (IRSTransition)transition;
	}
	
	public static Transition asTransition(INode transition) {
		if (!(transition instanceof Transition)) 
			throw new InternalDesignException(DesignCause.NOT_TRANSITION, transition.toString());
		return (Transition)transition;
	}
	
	public static IRSTransition asIRSTransition(IRSNode transition) {
		if (!(transition instanceof IRSTransition)) 
			throw new InternalDesignException(DesignCause.NOT_IRS_TRANSITION, transition.toString());
		return (IRSTransition)transition;
	}

	public static IRSWorkflow asIRSWorkflow(Net net) {
		if (!(net instanceof IRSWorkflow)) 
			throw new InternalDesignException(DesignCause.NOT_IRS_WORKFLOW, net.toString());
		return (IRSWorkflow)net;
	}
	
	public static <T> Map<T, Integer> listToMap(List<T> list) {
		Map<T, Integer> map = new LinkedHashMap<T, Integer>();
		for (T element : list) {
			Integer count = map.get(element);
			if (count == null) count = 0;
			map.put(element, count + 1);
		}
		return map;
	}
	
	public static <T1, T2> Map<T2, Set<T1>> swap(Map<T1, Set<T2>> input) {
		Map<T2, Set<T1>> output = new LinkedHashMap<T2, Set<T1>>();
		for (Entry<T1, Set<T2>> entry : input.entrySet()) {
			for (T2 element : entry.getValue()) {
				Set<T1> set = output.get(element);
				if (set == null) {
					set = new LinkedHashSet<T1>();
					output.put(element, set);
				}
				set.add(entry.getKey());
			}
		}
		return output;
	}
}
